package tech.aistar.corejava.day16.nio;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @author success
 * @version 1.0
 * @description:本类用来演示:
 * @date 2019/8/5 0005
 */
@SuppressWarnings("all")
public class BioClient {
    public static void main(String[] args) {
        //模拟的是客户端
        try {
            //连接到哪个服务器 - 指定端口号
            Socket socket = new Socket("127.0.0.1",8888);

            //server发送数据到客户端
            //客户端负责接收数据
            InputStream in = socket.getInputStream();

            Scanner sc = new Scanner(in);

            //遍历服务器返回的结果,并且打印
            while(sc.hasNext()){
                System.out.println(sc.next());
            }
            //关闭sc
            sc.close();
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
@SuppressWarnings("all")
/**
 * 只能处理单个请求
 */
class BioMyServer{
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);

            //等待客户端连接
            //此处会一直进入到阻塞状态
            //1 - 接收客户端请求
            Socket socket = serverSocket.accept();
            System.out.println("after accept....");

            //服务器端发送数据给客户端
            //2 - 处理请求 - 可能是负责的业务逻辑
            OutputStream out = socket.getOutputStream();

            out.write("hello world\n".getBytes());

            out.close();
            socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
@SuppressWarnings("all")
//希望可以处理多个请求
class BioMyServer2{
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);

            //等待客户端连接
            //此处会一直进入到阻塞状态
            //1 - 接收客户端请求

            while(true){
                Socket socket = serverSocket.accept();
                System.out.println("after accept....");

                //服务器端发送数据给客户端
                //2 - 处理请求 - 可能是负责的业务逻辑
                OutputStream out = socket.getOutputStream();

                out.write("hello world\n".getBytes());

                out.close();
            }


            //out.close();
            //socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@SuppressWarnings("all")
//希望可以处理多个请求
class BioMyServer3{
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);

            //等待客户端连接
            //此处会一直进入到阻塞状态
            //1 - 接收客户端请求

            while(true){
                //核心业务 - 接收请求的线程
                Socket socket = serverSocket.accept();
                System.out.println("after accept....");

                //服务器端发送数据给客户端
                //2 - 处理请求 - 可能是负责的业务逻辑

                //核心的业务2 - 处理请求
                new Thread(){
                    @Override
                    public void run() {
                        try {
                            OutputStream out = socket.getOutputStream();
                            out.write("hello world\n".getBytes());
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }

                    }
                }.start();
            }


            //out.close();
            //socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@SuppressWarnings("all")
//希望可以处理多个请求
class BioMyServer4{
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(8888);

            ExecutorService executorService = Executors.newCachedThreadPool();

            //等待客户端连接
            //此处会一直进入到阻塞状态
            //1 - 接收客户端请求

            while(true){
                //核心业务 - 接收请求的线程
                Socket socket = serverSocket.accept();
                System.out.println("after accept....");

                //服务器端发送数据给客户端
                //2 - 处理请求 - 可能是负责的业务逻辑

                //核心的业务2 - 处理请求
                executorService.submit(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            OutputStream out = socket.getOutputStream();
                            out.write("hello world\n".getBytes());
                            out.close();
                        } catch (IOException e) {
                            e.printStackTrace();
                        }
                    }
                });
            }


            //out.close();
            //socket.close();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

@SuppressWarnings("all")
class NNserver{
    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.bind(new InetSocketAddress(8888));
        serverSocketChannel.configureBlocking(false); //设置服务端操作都是非阻塞的

        Selector selector = Selector.open(); //选择器
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); //对客户端的accept事件关心

        while (true) {
            System.out.println("before===");
            selector.select(1000); //会阻塞住，直到有事件触发
            System.out.println("===");

            Set<SelectionKey> selectionKeys = selector.selectedKeys(); //看下有哪些事件被触发了
            System.out.println("selectionKeys:" + selectionKeys);

            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()) {
                SelectionKey key = iterator.next();

                if (key.isAcceptable()) {
                    //客户端 accept被触发了
                    ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel();

                    SocketChannel clientChannel = serverChannel.accept();
                    System.out.println("channel is acceptable");
                    clientChannel.configureBlocking(false);

                    //客户端channel注册OP_WRITE事件
                    clientChannel.register(selector, SelectionKey.OP_WRITE);
                } else if (key.isWritable()) {
                    //客户端可以往里写数据了

                    System.out.println("channel is writeable");
                    String data = "hello world\n";

                    //注意这里的是客户端的channel，因为是使用客户端channel注册OP_WRITE事件
                    SocketChannel clientChannel = (SocketChannel)key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(data.length());
                    buffer.put(data.getBytes());
                    buffer.flip();
                    clientChannel.write(buffer);
                }
                key.cancel(); //取消事件
                iterator.remove();
            }
        }
    }
}
